package org.mybatis.generator.api.plus;

import java.util.List;
import java.util.Properties;

import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.dom.java.Field;
import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
import org.mybatis.generator.api.dom.java.InnerClass;
import org.mybatis.generator.api.dom.java.JavaVisibility;
import org.mybatis.generator.api.dom.java.TopLevelClass;

/** @author wangfupeng */
public class MybatisPluginSerializable extends PluginAdapter {
	
	private FullyQualifiedJavaType serializable;

	public MybatisPluginSerializable() {
		this.serializable = new FullyQualifiedJavaType("java.io.Serializable");
	}

	public boolean validate(List<String> warnings) {
		return true;
	}

	public void setProperties(Properties properties) {
		super.setProperties(properties);
	}

	@Override
	public boolean modelBaseRecordClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
		makeSerializable(topLevelClass, introspectedTable);
		return true;
	}

	@Override
	public boolean modelPrimaryKeyClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
		makeSerializable(topLevelClass, introspectedTable);
		return true;
	}

	@Override
	public boolean modelRecordWithBLOBsClassGenerated(TopLevelClass topLevelClass,
			IntrospectedTable introspectedTable) {
		makeSerializable(topLevelClass, introspectedTable);
		return true;
	}

	@Override
	public boolean modelExampleClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
		topLevelClass.addImportedType(this.serializable);
		topLevelClass.addSuperInterface(this.serializable);
		Field field = new Field();
		field.setFinal(true);
		field.setInitializationString("1L");
		field.setName("serialVersionUID");
		field.setStatic(true);
		field.setType(new FullyQualifiedJavaType("long"));
		field.setVisibility(JavaVisibility.PRIVATE);
		this.context.getCommentGenerator().addFieldComment(field, introspectedTable);
		topLevelClass.addField(field);
		for (InnerClass innerClass : topLevelClass.getInnerClasses()) {
			if ("GeneratedCriteria".equals(innerClass.getType().getShortName())) {
				innerClass.addSuperInterface(this.serializable);
				addInnerClassField(innerClass, introspectedTable);
			}
			if ("Criteria".equals(innerClass.getType().getShortName())) {
				innerClass.addSuperInterface(this.serializable);
				addInnerClassField(innerClass, introspectedTable);
			}
			if ("Criterion".equals(innerClass.getType().getShortName())) {
				innerClass.addSuperInterface(this.serializable);
				addInnerClassField(innerClass, introspectedTable);
			}
		}
		return true;
	}

	protected void makeSerializable(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
		topLevelClass.addImportedType(this.serializable);
		topLevelClass.addSuperInterface(this.serializable);
		addTopLevelClassField(topLevelClass, introspectedTable);
	}
	
	protected void addTopLevelClassField(TopLevelClass topLevelClass,IntrospectedTable introspectedTable) {
		Field fieldInnerClass = new Field();
		fieldInnerClass.setFinal(true);
		fieldInnerClass.setInitializationString("1L");
		fieldInnerClass.setName("serialVersionUID");
		fieldInnerClass.setStatic(true);
		fieldInnerClass.setType(new FullyQualifiedJavaType("long"));
		fieldInnerClass.setVisibility(JavaVisibility.PRIVATE);
		this.context.getCommentGenerator().addFieldComment(fieldInnerClass, introspectedTable);
		topLevelClass.addField(fieldInnerClass);
	}
	
	protected void addInnerClassField(InnerClass innerClass,IntrospectedTable introspectedTable) {
		Field fieldInnerClass = new Field();
		fieldInnerClass.setFinal(true);
		fieldInnerClass.setInitializationString("1L");
		fieldInnerClass.setName("serialVersionUID");
		fieldInnerClass.setStatic(true);
		fieldInnerClass.setType(new FullyQualifiedJavaType("long"));
		fieldInnerClass.setVisibility(JavaVisibility.PRIVATE);
		this.context.getCommentGenerator().addFieldComment(fieldInnerClass, introspectedTable);
		innerClass.addField(fieldInnerClass);
	}

}
